package com.richard.library.http.converter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.NumberCodec;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.util.TypeUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by xiejiao on 2017/1/24.
 * json 转换(alibaba fastJson)
 */

public final class JsonConverter {

    static {
        TypeUtils.compatibleWithJavaBean = true;

        //浮点数值序列化配置
        DecimalFormat decimalFormat = new DecimalFormat("#.################");
        decimalFormat.setGroupingUsed(false);
        SerializeConfig.getGlobalInstance().put(Double.class, new NumberCodec(decimalFormat));
        SerializeConfig.getGlobalInstance().put(Float.class, new NumberCodec(decimalFormat));
    }

    public static String toJson(Object src) {
        return JSON.toJSONString(src);
    }

    public static JSONObject toJSONObject(Object object) {
        try {
            if (object instanceof String) {
                return JSON.parseObject(object.toString());
            }
            return JSON.parseObject(toJson(object));
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> T toObject(Object object, Class<T> clazz) {
        try {
            if (object instanceof String) {
                return JSON.parseObject(object.toString(), clazz);
            }
            return JSON.parseObject(toJson(object), clazz);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> T toObject(Object object, TypeReference<T> reference) {
        try {
            if (object instanceof String) {
                return JSON.parseObject(object.toString(), reference);
            }
            return JSON.parseObject(toJson(object), reference);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> T toObject(byte[] bytes, Class<T> clazz) {
        try {
            return toObject(new String(bytes), clazz);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> T toObject(byte[] bytes, TypeReference<T> reference) {
        try {
            return toObject(new String(bytes), reference);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> T toObject(Object object, Type type) {
        try {
            if (object instanceof String) {
                return JSON.parseObject(object.toString(), type);
            }
            return JSON.parseObject(toJson(object), type);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    //------------------------array----------------------------

    public static JSONArray toJSONArray(Object jsonArray) {
        try {
            if (jsonArray instanceof String) {
                return JSONArray.parseArray(jsonArray.toString());
            } else {
                return JSONArray.parseArray(toJson(jsonArray));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static <T> List<T> toObjectList(Object object, Class<T> clazz) {
        try {
            if (object instanceof String) {
                return JSON.parseArray(object.toString(), clazz);
            }
            return JSON.parseArray(toJson(object), clazz);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }


    /**
     * 获取FastJson 解析 Type
     */
    public static Type getType(Class<?> clazz) {
        Type superClass = clazz.getGenericSuperclass();
        if (superClass == null) {
            return Object.class;
        }

        if (!(superClass instanceof ParameterizedType)) {
            return Object.class;
        }

        Type oriType = ((ParameterizedType) superClass).getActualTypeArguments()[0];
        if (oriType instanceof Class) {
            return oriType;
        } else {
            ConcurrentMap<Type, Type> classTypeCache = new ConcurrentHashMap<>(16, 0.75f, 1);
            //修复在安卓环境中问题
            Type cachedType = classTypeCache.get(oriType);
            if (cachedType == null) {
                classTypeCache.putIfAbsent(oriType, oriType);
                cachedType = classTypeCache.get(oriType);
            }
            return cachedType;
        }
    }
}
